import axios from "axios";
import useUserStore from "@/store/modules/useUserStore";
import useSettingsStore from "@/store/modules/useSettingsStore";
import $http from "./http";
import $api from "./index";

const CACHE_EXPIRE_TIME = VITE_ENV.VITE_HTTP_CACHE_EXPIRE;
const CACHE_MAX = VITE_ENV.VITE_HTTP_CACHE_MAX;
const CACHE = VITE_ENV.VITE_HTTP_CACHE;
const RETRY_COUNT = VITE_ENV.VITE_HTTP_RETRY_COUNT;
const RETRY_DELAY = VITE_ENV.VITE_HTTP_RETRY_DELAY;
const succCode = [200, 0, 1000];
const CancelToken = axios.CancelToken;
//生成请求唯一key
function getReqKey(config) {
  if (!config) return;
  let params = config.params,
    data = config.data;
  if (params && typeof params == "object") {
    params = JSON.stringify(params);
  }
  if (data && typeof data == "object") {
    data = JSON.stringify(data);
  }
  return `${config.method}:${config.baseURL}${config.url}:${params}:${data}`;
}
//取消重复请求
class HttpPending {
  readonly pendingMap = new Map();
  addPending(config) {
    if (!config) return;
    const key = getReqKey(config);
    if (!this.pendingMap.has(key)) {
      this.pendingMap.set(key, config._cancel);
    } else {
      config._cancel({
        msg: `Repeat request:${key}`,
        _config: config
      });
    }
  }
  removePending(config) {
    if (!config) return;
    const key = getReqKey(config);
    if (this.pendingMap.has(key)) {
      this.pendingMap.delete(key);
    }
  }
  clear() {
    this.pendingMap.clear();
  }
}
//缓存请求数据
class HttpCache {
  readonly cacheMap = new Map();
  readonly STORAGE_KEY = "HTTP_CACHE_MAP";
  constructor() {
    const cache = localStorage.getItem(this.STORAGE_KEY);
    if (cache) {
      const obj: Object = JSON.parse(cache);
      this.cacheMap = new Map(Object.entries(obj));
    }
    window.addEventListener("unload", e => {
      localStorage.setItem(
        this.STORAGE_KEY,
        JSON.stringify(Object.fromEntries(this.cacheMap))
      );
    });
  }
  addCache(response) {
    if (!response) return;
    if (!CACHE || !response.config.cache) return;
    const codes = response.config.succCode ?? succCode;
    const key = getReqKey(response.config);
    const time = new Date().getTime();
    if (this.cacheMap.size >= CACHE_MAX) {
      let arr = Array.from(this.cacheMap);
      arr
        .sort((a, b) => {
          return a[1]._count ?? 0 - b[1]._count ?? 0;
        })
        .slice(0, this.cacheMap.size - CACHE_MAX + 1)
        .map(item => {
          this.cacheMap.delete(item[0]);
        });
    }
    if (codes.includes(response.data.code)) {
      response.data._cache = true;
      this.cacheMap.set(key, {
        data: response.data,
        time: time,
        expire: response.config.cacheExpire ?? CACHE_EXPIRE_TIME,
        _count: 0
      });
      return;
    }
  }
  checkCache(config) {
    if (!config) return;
    if (!CACHE || !config.cache) return;
    const key = getReqKey(config);
    const time = new Date().getTime();
    if (config.cache && this.cacheMap.has(key)) {
      const cache = this.cacheMap.get(key);
      if (time - cache.time < (config.cacheExpire ?? CACHE_EXPIRE_TIME)) {
        cache._count++;
        config._cancel({
          msg: `Cached request:${key}`,
          data: cache.data,
          _config: config,
          _cache: true,
          _time: cache.time
        });
      } else {
        this.cacheMap.delete(key);
      }
    }
  }
  clear() {
    this.cacheMap.clear();
    localStorage.removeItem(this.STORAGE_KEY);
  }
}

//添加取消请求功能
function addReqCancel(config) {
  if (!config) return;
  const source = CancelToken.source();
  config.cancelToken = source.token;
  config._cancel = source.cancel;
}
//添加请求头
function addHeaders(config) {
  const settingsStore = useSettingsStore();
  const lang = settingsStore.getLang;
  if (config._external) return;
  if (lang) config.headers["lang"] = `${lang}`;
}
//检查token
function checkReqAuth(config) {
  if (!config) return;
  const userStore = useUserStore();
  const key = getReqKey(config);
  const token = userStore.getToken;
  //const token='Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoZW50aWNhdGlvbk1ldGhvZCI6Im1vYmlsZSIsInVzZXJfbmFtZSI6IjEzODM1MTAwNDI3Iiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTY1MDQ5NDM1MywidXNlcklkIjoxNTE0MDc4NTk0OTE2NDk5NDU4LCJqdGkiOiJmYWE5NWI2MS1jMzg2LTQ2YjAtYWQxYy00MWU4Y2VjMzMwYTEiLCJjbGllbnRfaWQiOiJ5ZnMtYXBwIiwidXNlcm5hbWUiOiIxMzgzNTEwMDQyNyJ9.DdB_34Yp6aQ-LheDA2r-x_raSjlRedvXM2gYvLEITgSCSwHYYuT2aP7wWe83tL7W1rY95znkXzRxa29PgZ744naAEHIsqwvCMEC0ngPzGP4q-91KiczyaHmnXqxknPCMliF8jIJpHu93p2sPYDwVZrKk4gUUOmh9dgtishFf4Gc'
  if (!config._external) {
    addHeaders(config);
    if (token) config.headers["Authorization"] = `${token}`;
  }
  if (config.reqAuth && !token) {
    config._cancel({
      msg: `Auth request:${key}`,
      _config: config
    });
  }
}
//请求失败重连
async function httpRetry(config) {
  if (!config) return;
  config._retryCount ??= 0;
  if (config._retryCount >= RETRY_COUNT) return;
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      config._retryCount++;
      $http(config)
        .then(res => {
          resolve(res);
        })
        .catch(err => {
          reject(err);
        });
    }, RETRY_DELAY);
  });
}
//刷新token
async function refreshTokenAndRetry(config) {
  try {
    await $api.user.refreshToken();
    return await $http(config);
  } catch (error) {
    const userStore = useUserStore();
    userStore.clear();
  }
}
export {
  HttpPending,
  HttpCache,
  getReqKey,
  addReqCancel,
  checkReqAuth,
  httpRetry,
  refreshTokenAndRetry
};
